/*
 * Copyright 2021-2030 itbox.cn All right reserved. This software is the confidential and proprietary information
 * of itbox.cn ("Confidential Information"). You shall not disclose such Confidential Information and shall use it
 * only in accordance with the terms of the license agreement you entered into with itbox.cn.
 */
package cn.itbox.uap.common.interceptor;

import jakarta.servlet.http.HttpServletRequest;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
import org.springframework.lang.NonNull;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.Objects;

/**
 * @BelongProject uap
 * @BelongPackage cn.itbox.uap.domain.config
 * @Description TODO
 * @ClassName FeignRequestInterceptor
 * @Author xingc
 * @Date 2023/12/26 11:50
 * @Version 1.0.0
 */
@Slf4j
public class FeignRequestInterceptor implements RequestInterceptor, WebMvcRegistrations {

    @Override
    public void apply(RequestTemplate requestTemplate) {

        //// 透传Request Header
        //transfer(requestTemplate);

        // 透传链路跟踪的参数
        trace(requestTemplate);
    }

    /**
     * 透传链路跟踪的参数
     *
     * @param template
     */
    private void trace(RequestTemplate template) {
        String token = TraceUtil.getToken();
        template.removeHeader(Constants.TOKEN);
        template.header(Constants.TOKEN, token);

        template.removeHeader(Constants.AUTHORIZATION);
        template.header(Constants.AUTHORIZATION, token);

        String userId = TraceUtil.getUserId();
        template.removeHeader(Constants.USER_ID);
        template.header(Constants.USER_ID, userId);


        String userName = TraceUtil.getUserName();
        template.removeHeader(Constants.USER_NAME);

        if(StringUtils.hasText(userName)){
            userName=URLEncodeUtil.encode(userName, StandardCharsets.UTF_8);
        }

        template.header(Constants.USER_NAME, userName);



        String nickName = TraceUtil.getNickName();
        template.removeHeader(Constants.NICK_NAME);

        if(StringUtils.hasText(nickName)){
            nickName=URLEncodeUtil.encode(nickName, StandardCharsets.UTF_8);
        }

        template.header(Constants.NICK_NAME, nickName);




        String authMode = TraceUtil.getAuthMode();
        template.removeHeader(Constants.AUTH_MODE);
        template.header(Constants.AUTH_MODE, authMode);


        String mseTag = TraceUtil.getMseTag();
        template.removeHeader(Constants.X_MSE_TAG);
        template.header(Constants.X_MSE_TAG, mseTag);

        String traceId = TraceUtil.getTraceId();
        template.removeHeader(Constants.TRACE_ID);
        template.header(Constants.TRACE_ID, traceId);

        template.header(Constants.X_FEIGN_TAG, "1");


        String appCode = TraceUtil.getAppCode();
        template.removeHeader(Constants.APP_CODE);
        template.header(Constants.APP_CODE, appCode);

        String gwRequestId = TraceUtil.getGwRequestId();
        template.removeHeader(Constants.X_GW_REQUEST_ID);
        template.header(Constants.X_GW_REQUEST_ID, gwRequestId);

        String url = template.feignTarget().url() + template.request().url();
        log.info("FeignRequestInterceptor url={} traceId={}, mseTag={}, token={}, userId={},userName={},nickname={},authMode={}", url, traceId, mseTag, token, userId, userName,nickName, authMode);
    }

    /**
     * 透传Request Header
     *
     * @param template
     */
    private void transfer(RequestTemplate template) {
        HttpServletRequest request = getHttpServletRequest();
        if (Objects.isNull(request)) {
            return;
        }

        Enumeration<String> headerNames = request.getHeaderNames();
        if (null == headerNames || false == headerNames.hasMoreElements()) {
            return;
        }

        while (headerNames.hasMoreElements()) {
            String key = headerNames.nextElement();
            // 跳过content-length，因为feign会自动设置content-length
            if ("content-length".equalsIgnoreCase(key)) {
                continue;
            }
            String value = request.getHeader(key);
            template.header(key, value);
        }
    }

    private HttpServletRequest getHttpServletRequest() {
        try {
            // 这种方式获取的HttpServletRequest是线程安全的
            return ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        } catch (Exception e) {
            return null;
        }
    }

    private static class FeignRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
        @Override
        protected boolean isHandler(@NonNull Class<?> beanType) {
            return super.isHandler(beanType) &&
                    beanType.getAnnotation(FeignClient.class) == null;
        }
    }

}
